<!--
Copyright © 2017, Che-Wei Hsu <cwxhsu@gmail.com>
This file is part of the MintCM.
Some rights reserved. See README.
-->

<html>

<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<link rel="stylesheet" href="../css/mcm_style.css">
</head>

<body class="css_body">

<div class="css_div_box_frame_full">
  <div class="css_div_box_title">chapter 04-02</div>
  <div class="css_div_box_content">
  </div>
</div>
<br>

<div class="css_div_box_frame_full">
  <div class="css_div_box_title">資料狀態的取得 (模組端程式) (基本模式)</div>
  <div class="css_div_box_content">
    <br>

    此章節說明內部模組如何取得資料狀態.
    <br><br><br>

    透過取得資料的狀態可以知道那些資料被修改 (設定/增加/刪除), 哪修資料沒有被修改,
    就可以只針對被修改的資料做處理.
    <br><br>

    舉例 :<br>
    目前有三筆資料,<br>
    device.vap.#1<br>
    device.vap.#2<br>
    device.vap.#3<br>
    做了下面的設定,<br>
    [set] device.vap.#1<br>
    [del] device.vap.#3<br>
    [add] device.vap.#4<br>
    呼叫內部模組處理時, 內部模組讀出資料的狀態就可以知道,<br>
    device.vap.#1 被設定<br>
    device.vap.#2 無修改<br>
    device.vap.#3 被刪除<br>
    device.vap.#4 被增加<br>
    之後就可以只針對被修改的資料做處理.
    <br><br><br>

    在 mcm_daemon 處理資料的流程中 <a href="mcm_0401.html#hook_0401_submit_flow_01">[詳細][B]</a> :<br>
    在 [B04] 的點, 內部模組可以取得資料的修改狀態 ([B03] 的狀態), 方便做後續的處理.
    <br><br>

  </div>
</div>
<br>

<div class="css_div_box_frame_full">
  <div class="css_div_box_title">變數格式的說明</div>
  <div class="css_div_box_content">
    <br>

    使用的資料模型範例, 參考 <a href="mcm_0202.html#hook_0202_data_profile_01">#02-02#</a>.
    <br><br><br>

    <div class="css_div_hook" id="hook_0402_this_session_01"></div>
    <font class="css_font_b1">[struct mcm_service_session_t *this_session]</font><br>
    請求端的連線資訊.<br>
    可以讀取的結構成員 :<br>
    <table class="css_table_list2">
      <tr>
        <td class="css_td_list2_l1">
          <font class="css_font_r1">MCM_DTYPE_LIST_TD</font><br>
          <font class="css_font_g1">call_from</font>
        </td>
        <td class="css_td_list2_r1">
          表示是誰呼叫內部模組 <a href="mcm_0302.html#hook_0302_call_from_01">[詳細]</a>
        </td>
      </tr>
    </table>
    <br><br>

    <div class="css_div_hook" id="hook_0402_mask_path_01"></div>
    <font class="css_font_b1">[char *mask_path]</font><br>
    取得 group 的資訊的路徑. <a href="mcm_0302.html#hook_0302_mask_path_01">[詳細]</a>
    <br><br><br>

    <div class="css_div_hook" id="hook_0402_mix_path_01"></div>
    <font class="css_font_b1">[char *mix_path]</font><br>
    存取多個 entry 的路徑. <a href="mcm_0302.html#hook_0302_mix_path_01">[詳細]</a>
    <br><br><br>

    <div class="css_div_hook" id="hook_0402_full_path_01"></div>
    <font class="css_font_b1">[char *full_path]</font><br>
    存取的目標 entry 或 member 的路徑. <a href="mcm_0302.html#hook_0302_full_path_01">[詳細]</a>
    <br><br><br>

    <div class="css_div_hook" id="hook_0402_typedef_01"></div>
    <font class="css_font_b1">紀錄 member 資料的狀態的型態.</font><br>
    <table class="css_table_list2">
      <tr>
        <td class="css_td_list2_t1">對應型態</td>
        <td class="css_td_list2_t1">printf 格式</td>
      </tr>
      <tr>
        <td class="css_td_list2_r1">MCM_DTYPE_DS_TD</td>
        <td class="css_td_list2_r1">MCM_DTYPE_DS_PF</td>
      </tr>
    </table>
    <br><br>

    <div class="css_div_hook" id="hook_0402_typedef_02"></div>
    <font class="css_font_b1">紀錄 entry 資料的狀態的型態</font><br>
    可以當作 struct 來存取, member 是成員變數.<br>
    必須先寫好資料模型檔並編譯完成,
    <font class="css_font_b1">mint_cm/mcm_lib/mcm_lheader/mcm_data_exinfo_auto.h</font>
    會產生對應的結構資料.<br>
    例如 :<br>
    <div class="css_div_block">
      vap 會被編譯出 :<br><br>
      // device.vap.*<br>
      <font class="css_font_p1">struct</font>
      <font class="css_font_g1">mcm_ds_device_vap_t</font><br>
      {<br	>
      </font>
      <font class="css_font_r1">
      &nbsp;&nbsp;&nbsp;&nbsp;MCM_DTYPE_DS_TD ekey;<br>
      &nbsp;&nbsp;&nbsp;&nbsp;MCM_DTYPE_DS_TD ssid;<br>
      &nbsp;&nbsp;&nbsp;&nbsp;MCM_DTYPE_DS_TD channel;<br>
      </font>
      } <font class="css_font_p1">/*__attribute__((packed))*/</font>;
    </div>
    <br><br>
    如果需要修改結構的對齊方式,
    修改 <font class="css_font_b1">mint_cm/mcm_build/mcm_build.c</font> 並重新編譯全部.<br>
    <div class="css_div_block">
    <font class="css_font_p1">#define</font>
    <font class="css_font_g1">MCM_DATA_EXINFO_DATA_STATUS_ATTRIBUTE</font>
    <font class="css_font_r1">"/*__attribute__((packed))*/"</font>
    </div>
    <br><br>

  </div>
</div>
<br>

<div class="css_div_box_frame_full">
  <div class="css_div_box_title">資料狀態的說明</div>
  <div class="css_div_box_content">
    <br>

    <div class="css_div_hook" id="hook_0402_data_status_01"></div>
    <font class="css_font_b1">狀態的值和意義</font><br>
    <table class="css_table_list2">
      <tr>
        <td class="css_td_list2_t3" colspan="2">
          <font class="css_font_g1">MCM_DATA_STATUS_CHANGE_FLAG</font><br>
          <font class="css_font_b1">(mint_cm/mcm_lib/mcm_lheader/mcm_control.h)</font>
        </td>
      </tr>
      <tr>
        <td class="css_td_list2_l2">MCM_DSCHANGE_NONE</td>
        <td class="css_td_list2_r1">資料無修改</td>
      </tr>
      <tr>
        <td class="css_td_list2_l2">MCM_DSCHANGE_SET</td>
        <td class="css_td_list2_r1">資料被設定</td>
      </tr>
      <tr>
        <td class="css_td_list2_l2">MCM_DSCHANGE_ADD</td>
        <td class="css_td_list2_r1">資料被增加</td>
      </tr>
      <tr>
        <td class="css_td_list2_l2">MCM_DSCHANGE_DEL</td>
        <td class="css_td_list2_r1">資料被刪除</td>
      </tr>
    </table>
    取出的狀態值需要和 <font class="css_font_r1">MCM_DSCHANGE_MASK</font> 做
    <font class="css_font_b1">AND</font> 運算才可和上述的值做比對.<br>
    資料模型中 $(type) 為 ek 的 member 用來代表整個 entry 的狀態.
    <br><br><br>

    <table class="css_table_box">
      <tr>
        <td class="css_td_box">
          <font class="css_font_b2">MCM_DSCHANGE_SET</font>
          <br><br>
          作用的範圍 :<br>
          被設定的 entry 和被設定的 member.
          <br><br>
          對 child-entry 的影響 :<br>
          無.
          <br><br>
          範例 :<br>
          <div class="css_div_block">
            設定 device.system.date<br>
            設定 device.system.ip_addr<br>
            設定 device.vap.@1.channel
          </div>
          <br>
          <div class="css_div_block">
            <font class="css_font_g1">device.system</font><br>
            被設定, 有狀態 (entry)<br><br>
            <font class="css_font_g1">device.system.date</font><br>
            被設定, 有狀態 (member)<br><br>
            <font class="css_font_g1">device.system.ip_addr</font><br>
            被設定, 有狀態 (member)<br><br>
            device.system.uptime<br>
            沒設定, 沒狀態 (member)<br><br>
            device.system.loading<br>
            沒設定, 沒狀態 (member)<br><br>
            <font class="css_font_g1">device.vap.@1</font><br>
            被設定, 有狀態 (entry)<br><br>
            device.vap.@1.ssid<br>
            沒設定, 沒狀態 (member)<br><br>
            <font class="css_font_g1">device.vap.@1.channel</font><br>
            被設定, 有狀態 (member)<br><br>
            device.vap.@1.extra<br>
            parent-entry 被設定, 但是不會影響 child-entry, 所以沒狀態
          </div>
        </td>
      </tr>
    </table>
    <br>

    <table class="css_table_box">
      <tr>
        <td class="css_td_box">
          <font class="css_font_b2">MCM_DSCHANGE_ADD</font>
          <br><br>
          作用的範圍 :<br>
          被增加的 entry 和所有的 member.
          <br><br>
          對 child-entry 的影響 :<br>
          如果 parent-group 是 gd 類型而 child-entry 是 gs 類型, 當 parent-group 增加 entry 時, 也會一併被增加,
          這時候也會被貼上狀態.
          <br><br>
          範例 :<br>
          <div class="css_div_block">
            增加 device.vap.#45
          </div>
          <br>
          <div class="css_div_block">
            <font class="css_font_g1">device.vap.#45</font><br>
            <font class="css_font_g1">device.vap.#45.ssid</font><br>
            <font class="css_font_g1">device.vap.#45.channel</font><br>
            被增加, 有狀態<br><br>
            <font class="css_font_g1">device.vap.#45.extra</font><br>
            <font class="css_font_g1">device.vap.#45.extra.hidden</font><br>
            <font class="css_font_g1">device.vap.#45.extra.tx_power</font><br>
            parent-entry 被增加, 也會跟著被增加, 有狀態
          </div>
        </td>
      </tr>
    </table>
    <br>

    <table class="css_table_box">
      <tr>
        <td class="css_td_box">
          <font class="css_font_b2">MCM_DSCHANGE_DEL</font>
          <br><br>
          作用的範圍 :<br>
          被刪除的 entry 和所有的 member.
          <br><br>
          對 child-entry 的影響 :<br>
          所有的 child-entry 都會被刪除, 都會貼上狀態.
          <br><br>
          範例 :<br>
          <div class="css_div_block">
            刪除 device.vap.#15
          </div>
          <br>
          <div class="css_div_block">
            <font class="css_font_g1">device.vap.#15</font><br>
            <font class="css_font_g1">device.vap.#15.ssid</font><br>
            <font class="css_font_g1">device.vap.#15.channel</font><br>
            被刪除, 有狀態<br><br>
            <font class="css_font_g1">device.vap.#15.extra</font><br>
            <font class="css_font_g1">device.vap.#15.extra.hidden</font><br>
            <font class="css_font_g1">device.vap.#15.extra.tx_power</font><br>
            parent-entry 被刪除, 也會跟著被刪除, 有狀態<br><br>
            <font class="css_font_g1">device.vap.#15.station.#30</font><br>
            <font class="css_font_g1">device.vap.#15.station.#30.mac_addr</font><br>
            <font class="css_font_g1">device.vap.#15.station.#30.rule</font><br>
            parent-entry 被刪除, 也會跟著被刪除, 有狀態<br><br>
            <font class="css_font_g1">device.vap.#15.station.#33</font><br>
            <font class="css_font_g1">device.vap.#15.station.#33.mac_addr</font><br>
            <font class="css_font_g1">device.vap.#15.station.#33.rule</font><br>
            parent-entry 被刪除, 也會跟著被刪除, 有狀態
          </div>
        </td>
      </tr>
    </table>
    <br>

  </div>
</div>
<br>

<div class="css_div_box_frame_full">
  <div class="css_div_box_title">可用的函式</div>
  <div class="css_div_box_content">
    <br>

    <div class="css_div_hook" id="hook_0402_mcm_config_get_alone_status_by_path_01"></div>
    <table class="css_table_box">
      <tr>
        <td class="css_td_box">
          <font class="css_font_b2">mcm_config_get_alone_status_by_path</font><br>
          讀出 member 的狀態.<br>
          <table class="css_table_list2">
            <tr>
              <td class="css_td_list2_t1">參數</td>
              <td class="css_td_list2_t1">說明</td>
            </tr>
            <tr>
              <td class="css_td_list2_l1">
                <font class="css_font_r1">struct mcm_service_session_t *</font><br>
                <font class="css_font_g1">this_session</font>
              </td>
              <td class="css_td_list2_r1">
                請求端的連線資訊
              </td>
            </tr>
            <tr>
              <td class="css_td_list2_l1">
                <font class="css_font_r1">char *</font><br>
                <font class="css_font_g1">full_path</font><br>
              </td>
              <td class="css_td_list2_r1">
                目標的路徑 <a href="#hook_0402_full_path_01">[詳細]</a><br>
                <font class="css_font_p1">[member 格式][index / key 模式]</font>
              </td>
            </tr>
            <tr>
              <td class="css_td_list2_l1">
                <font class="css_font_r1">MCM_DTYPE_DS_TD *</font><br>
                <font class="css_font_g1">data_buf</font><br>
              </td>
              <td class="css_td_list2_r1">
                紀錄資料的狀態的緩衝 (狀態的資料型態 <a href="#hook_0402_typedef_01">[詳細]</a>)
              </td>
            </tr>
          </table>
          <table class="css_table_list2">
            <tr>
              <td class="css_td_list2_t1">回傳</td>
              <td class="css_td_list2_t1">說明</td>
            </tr>
            <tr>
              <td class="css_td_list2_l2">&gt;= MCM_RCODE_PASS</td>
              <td class="css_td_list2_r1">成功</td>
            </tr>
            <tr>
              <td class="css_td_list2_l2">&nbsp;&lt; MCM_RCODE_PASS<br>(MCM_RCODE_CONFIG_NOT_FIND_STORE)</td>
              <td class="css_td_list2_r1">錯誤, 目標 entry 不存在</td>
            </tr>
            <tr>
              <td class="css_td_list2_l2">&nbsp;&lt; MCM_RCODE_PASS<br>(other)</td>
              <td class="css_td_list2_r1">錯誤, 其他錯誤</td>
            </tr>
          </table>
          <br>
          範例 :<br>
<pre class="css_pre_code">
外部程式部分

#include &lt;errno.h&gt;
#include &lt;stdio.h&gt;
#include &lt;string.h&gt;
#include &lt;stdlib.h&gt;
#include "mcm_lib/mcm_lheader/mcm_type.h"
#include "mcm_lib/mcm_lheader/mcm_size.h"
#include "mcm_lib/mcm_lheader/mcm_connect.h"
#include "mcm_lib/mcm_lheader/mcm_return.h"
#include "mcm_lib/mcm_lheader/mcm_data_exinfo_auto.h"
#include "mcm_lib/mcm_lulib/mcm_lulib_api.h"

#define DMSG(msg_fmt, msgs...) printf("%s(%04u): " msg_fmt "\n", __FILE__, __LINE__, ##msgs)

int main(
    int argc,
    char **argv)
{
    char *path1;
    struct mcm_lulib_lib_t self_lulib;
    MCM_DTYPE_ISLL_TD uptime;
    struct mcm_dv_device_vap_t vap_v;

    self_lulib.socket_path = "@mintcm";
    self_lulib.call_from = MCM_CFROM_USER;
    self_lulib.session_permission = MCM_SPERMISSION_RW;
    self_lulib.session_stack_size = 0;
    if(mcm_lulib_init(&self_lulib) < MCM_RCODE_PASS)
    {
        DMSG("call mcm_lulib_init() fail");
        goto FREE_01;
    }

    // 範例-01 : 設定 device.system.uptime
    path1 = "device.system.uptime";
    uptime = 123456;
    DMSG("[set] %s", path1);
    if(mcm_lulib_set_alone(&self_lulib, path1, &uptime, sizeof(uptime)) < MCM_RCODE_PASS)
    {
        DMSG("call mcm_lulib_set_alone(%s) fail", path1);
        goto FREE_02;
    }

    // 範例-02a : 設定 device.vap.@2
    path1 = "device.vap.@2";
    memset(&vap_v, 0, sizeof(struct mcm_dv_device_vap_t));
    snprintf(vap_v.ssid, sizeof(vap_v.ssid), "ap-1234");
    vap_v.channel = 14;
    DMSG("[set] %s", path1);
    if(mcm_lulib_set_entry(&self_lulib, path1, &vap_v, sizeof(vap_v)) < MCM_RCODE_PASS)
    {
        DMSG("call mcm_lulib_set_entry(%s) fail", path1);
        goto FREE_02;
    }

    // 範例 02b : 增加 device.vap.#51
    path1 = "device.vap.#51";
    DMSG("[add] %s", path1);
    if(mcm_lulib_add_entry(&self_lulib, path1, NULL, NULL, 0) < MCM_RCODE_PASS)
    {
        DMSG("call mcm_lulib_add_entry(%s) fail", path1);
        goto FREE_02;
    }

    // 範例 02c : 刪除 device.vap.#8
    path1 = "device.vap.#8";
    DMSG("[del] %s", path1);
    if(mcm_lulib_del_entry(&self_lulib, path1) < MCM_RCODE_PASS)
    {
        DMSG("call mcm_lulib_del_entry(%s) fail", path1);
        goto FREE_02;
    }

    // 呼叫內部模組處理.
    path1 = "mcm_module_status_test_get_alone";
    DMSG("[run] %s", path1);
    if(mcm_lulib_run(&self_lulib, path1, NULL, 0, NULL, NULL) < MCM_RCODE_PASS)
    {
        DMSG("call mcm_lulib_run(%s) fail", path1);
        goto FREE_02;
    }

FREE_02:
    mcm_lulib_exit(&self_lulib);
FREE_01:
    return 0;
}
</pre>
<br>
<pre class="css_pre_code">
內部模組部分

#include &lt;stdio.h&gt;
#include "mcm_lib/mcm_lheader/mcm_type.h"
#include "mcm_lib/mcm_lheader/mcm_size.h"
#include "mcm_lib/mcm_lheader/mcm_control.h"
#include "mcm_lib/mcm_lheader/mcm_connect.h"
#include "mcm_lib/mcm_lheader/mcm_return.h"
#include "mcm_lib/mcm_lheader/mcm_debug.h"
#include "mcm_lib/mcm_lheader/mcm_data_exinfo_auto.h"
#include "../mcm_service_handle_define.h"
#include "../mcm_config_handle_extern.h"

#define DMSG(msg_fmt, msgs...) printf("%s(%04u): " msg_fmt "\n", __FILE__, __LINE__, ##msgs)

void show_status(
    char *case_name,
    char *path_name,
    char *post_name,
    MCM_DTYPE_DS_TD status_code)
{
    char *status_type = NULL;

    switch(status_code)
    {
        case MCM_DSCHANGE_NONE:
            status_type = "non";
            break;
        case MCM_DSCHANGE_SET:
            status_type = "set";
            break;
        case MCM_DSCHANGE_ADD:
            status_type = "add";
            break;
        case MCM_DSCHANGE_DEL:
            status_type = "del";
            break;
    }

    DMSG("[%s] %s %s%s", case_name, status_type, path_name, post_name);
}

int mcm_module_status_test_get_alone(
    struct mcm_service_session_t *this_session)
{
    int fret = MCM_RCODE_MODULE_INTERNAL_ERROR;
    char *path1;
    MCM_DTYPE_DS_TD tmp_status;

    // 範例 : 取得 device 的狀態.
    // 沒有修改 device, 會是 MCM_DSCHANGE_NONE.
    path1 = "device.ekey";
    if(mcm_config_get_alone_status_by_path(this_session, path1, &tmp_status) < MCM_RCODE_PASS)
    {
        DMSG("call mcm_config_get_alone_status_by_path(%s) fail", path1);
        goto FREE_01;
    }
    tmp_status &= MCM_DSCHANGE_MASK;
    show_status("alone", path1, "", tmp_status);

    // 範例-01 : 取得 device.system 的狀態.
    // 設定 device.system.uptime, 會是 MCM_DSCHANGE_SET.
    path1 = "device.system.ekey";
    if(mcm_config_get_alone_status_by_path(this_session, path1, &tmp_status) < MCM_RCODE_PASS)
    {
        DMSG("call mcm_config_get_alone_status_by_path(%s) fail", path1);
        goto FREE_01;
    }
    tmp_status &= MCM_DSCHANGE_MASK;
    show_status("alone", path1, "", tmp_status);

    // 範例-01-01 : 取得 device.system.uptime 的狀態.
    // 設定 device.system.uptime, 會是 MCM_DSCHANGE_SET.
    path1 = "device.system.uptime";
    if(mcm_config_get_alone_status_by_path(this_session, path1, &tmp_status) < MCM_RCODE_PASS)
    {
        DMSG("call mcm_config_get_alone_status_by_path(%s) fail", path1);
        goto FREE_01;
    }
    tmp_status &= MCM_DSCHANGE_MASK;
    show_status("alone", path1, "", tmp_status);

    // 範例-01-02 : 取得 device.system.loading 的狀態.
    // 沒修改 device.system.loading, 會是 MCM_DSCHANGE_NONE.
    path1 = "device.system.loading";
    if(mcm_config_get_alone_status_by_path(this_session, path1, &tmp_status) < MCM_RCODE_PASS)
    {
        DMSG("call mcm_config_get_alone_status_by_path(%s) fail", path1);
        goto FREE_01;
    }
    tmp_status &= MCM_DSCHANGE_MASK;
    show_status("alone", path1, "", tmp_status);

    // 範例-02a : 取得 device.vap.@2 的狀態.
    // 設定 device.vap.@2, 會是 MCM_DSCHANGE_SET.
    path1 = "device.vap.@2.ekey";
    if(mcm_config_get_alone_status_by_path(this_session, path1, &tmp_status) < MCM_RCODE_PASS)
    {
        DMSG("call mcm_config_get_alone_status_by_path(%s) fail", path1);
        goto FREE_01;
    }
    tmp_status &= MCM_DSCHANGE_MASK;
    show_status("alone", path1, "", tmp_status);

    // 範例-02a-01 : 取得 device.vap.@2.extra 的狀態.
    // 設定不會影響到 child-group, 所以會是 MCM_DSCHANGE_NONE.
    path1 = "device.vap.@2.extra.ekey";
    if(mcm_config_get_alone_status_by_path(this_session, path1, &tmp_status) < MCM_RCODE_PASS)
    {
        DMSG("call mcm_config_get_alone_status_by_path(%s) fail", path1);
        goto FREE_01;
    }
    tmp_status &= MCM_DSCHANGE_MASK;
    show_status("alone", path1, "", tmp_status);

    // 範例-02b : 取得 device.vap.#51 的狀態.
    // 增加 device.vap.#51, 會是 MCM_DSCHANGE_ADD.
    path1 = "device.vap.#51.ekey";
    if(mcm_config_get_alone_status_by_path(this_session, path1, &tmp_status) < MCM_RCODE_PASS)
    {
        DMSG("call mcm_config_get_alone_status_by_path(%s) fail", path1);
        goto FREE_01;
    }
    tmp_status &= MCM_DSCHANGE_MASK;
    show_status("alone", path1, "", tmp_status);

    // 範例-02b-01 : 取得 device.vap.#51.extra 的狀態.
    // 增加會一起增加 gs 類型的 child-group, 所以會是 MCM_DSCHANGE_ADD.
    path1 = "device.vap.#51.extra.ekey";
    if(mcm_config_get_alone_status_by_path(this_session, path1, &tmp_status) < MCM_RCODE_PASS)
    {
        DMSG("call mcm_config_get_alone_status_by_path(%s) fail", path1);
        goto FREE_01;
    }
    tmp_status &= MCM_DSCHANGE_MASK;
    show_status("alone", path1, "", tmp_status);

    // 範例-02c : 取得 device.vap.#8 的狀態.
    // 刪除 device.vap.#8, 會是 MCM_DSCHANGE_DEL.
    path1 = "device.vap.#8.ekey";
    if(mcm_config_get_alone_status_by_path(this_session, path1, &tmp_status) < MCM_RCODE_PASS)
    {
        DMSG("call mcm_config_get_alone_status_by_path(%s) fail", path1);
        goto FREE_01;
    }
    tmp_status &= MCM_DSCHANGE_MASK;
    show_status("alone", path1, "", tmp_status);

    // 範例-02c-01 : 取得 device.vap.#8.extra 的狀態.
    // 刪除會一起刪除 child-group, 所以會是 MCM_DSCHANGE_DEL.
    path1 = "device.vap.#8.extra.ekey";
    if(mcm_config_get_alone_status_by_path(this_session, path1, &tmp_status) < MCM_RCODE_PASS)
    {
        DMSG("call mcm_config_get_alone_status_by_path(%s) fail", path1);
        goto FREE_01;
    }
    tmp_status &= MCM_DSCHANGE_MASK;
    show_status("alone", path1, "", tmp_status);

    // 範例-02c-02 : 取得 device.vap.#8.station.@1 的狀態.
    // 刪除會一起刪除 child-group, 所以會是 MCM_DSCHANGE_DEL.
    path1 = "device.vap.#8.station.@1.ekey";
    if(mcm_config_get_alone_status_by_path(this_session, path1, &tmp_status) < MCM_RCODE_PASS)
    {
        DMSG("call mcm_config_get_alone_status_by_path(%s) fail", path1);
        goto FREE_01;
    }
    tmp_status &= MCM_DSCHANGE_MASK;
    show_status("alone", path1, "", tmp_status);

    // 範例-02d : 取得 device.vap.#23 的狀態.
    // 沒有修改 device.vap.#23, 會是 MCM_DSCHANGE_NONE.
    path1 = "device.vap.#23.ekey";
    if(mcm_config_get_alone_status_by_path(this_session, path1, &tmp_status) < MCM_RCODE_PASS)
    {
        DMSG("call mcm_config_get_alone_status_by_path(%s) fail", path1);
        goto FREE_01;
    }
    tmp_status &= MCM_DSCHANGE_MASK;
    show_status("alone", path1, "", tmp_status);

    fret = MCM_RCODE_PASS;
FREE_01:
    return fret;
}
</pre>
        </td>
      </tr>
    </table>
    <br>

    <div class="css_div_hook" id="hook_0402_mcm_config_get_entry_self_status_by_path_01"></div>
    <table class="css_table_box">
      <tr>
        <td class="css_td_box">
          <font class="css_font_b2">mcm_config_get_entry_self_status_by_path</font><br>
          讀出 entry 的狀態.<br>
          等同使用 mcm_config_get_alone_status_by_path() 取得資料模型中 $(type) 為 ek 類型的 member,
          如果只是要取得 entry 狀態使用此函式較方便快速.<br>
          <table class="css_table_list2">
            <tr>
              <td class="css_td_list2_t1">參數</td>
              <td class="css_td_list2_t1">說明</td>
            </tr>
            <tr>
              <td class="css_td_list2_l1">
                <font class="css_font_r1">struct mcm_service_session_t *</font><br>
                <font class="css_font_g1">this_session</font>
              </td>
              <td class="css_td_list2_r1">
                請求端的連線資訊
              </td>
            </tr>
            <tr>
              <td class="css_td_list2_l1">
                <font class="css_font_r1">char *</font><br>
                <font class="css_font_g1">full_path</font><br>
              </td>
              <td class="css_td_list2_r1">
                目標的路徑 <a href="#hook_0402_full_path_01">[詳細]</a><br>
                <font class="css_font_p1">[entry 格式][index / key 模式]</font>
              </td>
            </tr>
            <tr>
              <td class="css_td_list2_l1">
                <font class="css_font_r1">MCM_DTYPE_DS_TD *</font><br>
                <font class="css_font_g1">data_buf</font><br>
              </td>
              <td class="css_td_list2_r1">
                紀錄資料的狀態的緩衝 (狀態的資料型態 <a href="#hook_0402_typedef_01">[詳細]</a>)
              </td>
            </tr>
          </table>
          <table class="css_table_list2">
            <tr>
              <td class="css_td_list2_t1">回傳</td>
              <td class="css_td_list2_t1">說明</td>
            </tr>
            <tr>
              <td class="css_td_list2_l2">&gt;= MCM_RCODE_PASS</td>
              <td class="css_td_list2_r1">成功</td>
            </tr>
            <tr>
              <td class="css_td_list2_l2">&nbsp;&lt; MCM_RCODE_PASS<br>(MCM_RCODE_CONFIG_NOT_FIND_STORE)</td>
              <td class="css_td_list2_r1">錯誤, 目標 entry 不存在</td>
            </tr>
            <tr>
              <td class="css_td_list2_l2">&nbsp;&lt; MCM_RCODE_PASS<br>(other)</td>
              <td class="css_td_list2_r1">錯誤, 其他錯誤</td>
            </tr>
          </table>
          <br>
          範例 :<br>
<pre class="css_pre_code">
外部程式部分

#include &lt;errno.h&gt;
#include &lt;stdio.h&gt;
#include &lt;string.h&gt;
#include &lt;stdlib.h&gt;
#include "mcm_lib/mcm_lheader/mcm_type.h"
#include "mcm_lib/mcm_lheader/mcm_size.h"
#include "mcm_lib/mcm_lheader/mcm_connect.h"
#include "mcm_lib/mcm_lheader/mcm_return.h"
#include "mcm_lib/mcm_lheader/mcm_data_exinfo_auto.h"
#include "mcm_lib/mcm_lulib/mcm_lulib_api.h"

#define DMSG(msg_fmt, msgs...) printf("%s(%04u): " msg_fmt "\n", __FILE__, __LINE__, ##msgs)

int main(
    int argc,
    char **argv)
{
    char *path1;
    struct mcm_lulib_lib_t self_lulib;
    MCM_DTYPE_ISLL_TD uptime;
    struct mcm_dv_device_vap_t vap_v;

    self_lulib.socket_path = "@mintcm";
    self_lulib.call_from = MCM_CFROM_USER;
    self_lulib.session_permission = MCM_SPERMISSION_RW;
    self_lulib.session_stack_size = 0;
    if(mcm_lulib_init(&self_lulib) < MCM_RCODE_PASS)
    {
        DMSG("call mcm_lulib_init() fail");
        goto FREE_01;
    }

    // 範例-01 : 設定 device.system.uptime
    path1 = "device.system.uptime";
    uptime = 123456;
    DMSG("[set] %s", path1);
    if(mcm_lulib_set_alone(&self_lulib, path1, &uptime, sizeof(uptime)) < MCM_RCODE_PASS)
    {
        DMSG("call mcm_lulib_set_alone(%s) fail", path1);
        goto FREE_02;
    }

    // 範例-02a : 設定 device.vap.@2
    path1 = "device.vap.@2";
    memset(&vap_v, 0, sizeof(vap_v));
    snprintf(vap_v.ssid, sizeof(vap_v.ssid), "ap-1234");
    vap_v.channel = 14;
    DMSG("[set] %s", path1);
    if(mcm_lulib_set_entry(&self_lulib, path1, &vap_v, sizeof(vap_v)) < MCM_RCODE_PASS)
    {
        DMSG("call mcm_lulib_set_entry(%s) fail", path1);
        goto FREE_02;
    }

    // 範例 02b : 增加 device.vap.#51
    path1 = "device.vap.#51";
    DMSG("[add] %s", path1);
    if(mcm_lulib_add_entry(&self_lulib, path1, NULL, NULL, 0) < MCM_RCODE_PASS)
    {
        DMSG("call mcm_lulib_add_entry(%s) fail", path1);
        goto FREE_02;
    }

    // 範例 02c : 刪除 device.vap.#8
    path1 = "device.vap.#8";
    DMSG("[del] %s", path1);
    if(mcm_lulib_del_entry(&self_lulib, path1) < MCM_RCODE_PASS)
    {
        DMSG("call mcm_lulib_del_entry(%s) fail", path1);
        goto FREE_02;
    }

    // 呼叫內部模組處理.
    path1 = "mcm_module_status_test_get_entry_self";
    DMSG("[run] %s", path1);
    if(mcm_lulib_run(&self_lulib, path1, NULL, 0, NULL, NULL) < MCM_RCODE_PASS)
    {
        DMSG("call mcm_lulib_run(%s) fail", path1);
        goto FREE_02;
    }

FREE_02:
    mcm_lulib_exit(&self_lulib);
FREE_01:
    return 0;
}
</pre>
<br>
<pre class="css_pre_code">
內部模組部分

#include &lt;stdio.h&gt;
#include "mcm_lib/mcm_lheader/mcm_type.h"
#include "mcm_lib/mcm_lheader/mcm_size.h"
#include "mcm_lib/mcm_lheader/mcm_control.h"
#include "mcm_lib/mcm_lheader/mcm_connect.h"
#include "mcm_lib/mcm_lheader/mcm_return.h"
#include "mcm_lib/mcm_lheader/mcm_debug.h"
#include "mcm_lib/mcm_lheader/mcm_data_exinfo_auto.h"
#include "../mcm_service_handle_define.h"
#include "../mcm_config_handle_extern.h"

#define DMSG(msg_fmt, msgs...) printf("%s(%04u): " msg_fmt "\n", __FILE__, __LINE__, ##msgs)

void show_status(
    char *case_name,
    char *path_name,
    char *post_name,
    MCM_DTYPE_DS_TD status_code)
{
    char *status_type = NULL;

    switch(status_code)
    {
        case MCM_DSCHANGE_NONE:
            status_type = "non";
            break;
        case MCM_DSCHANGE_SET:
            status_type = "set";
            break;
        case MCM_DSCHANGE_ADD:
            status_type = "add";
            break;
        case MCM_DSCHANGE_DEL:
            status_type = "del";
            break;
    }

    DMSG("[%s] %s %s%s", case_name, status_type, path_name, post_name);
}

int mcm_module_status_test_get_entry_self(
    struct mcm_service_session_t *this_session)
{
    int fret = MCM_RCODE_MODULE_INTERNAL_ERROR;
    char *path1;
    MCM_DTYPE_DS_TD tmp_status;

    // 範例 : 取得 device 的狀態.
    // 沒有修改 device, 會是 MCM_DSCHANGE_NONE.
    path1 = "device";
    if(mcm_config_get_entry_self_status_by_path(this_session, path1, &tmp_status)
                                                < MCM_RCODE_PASS)
    {
        DMSG("call mcm_config_get_entry_self_status_by_path(%s) fail", path1);
        goto FREE_01;
    }
    tmp_status &= MCM_DSCHANGE_MASK;
    show_status("entry-self", path1, "", tmp_status);

    // 範例-01 : 取得 device.system 的狀態.
    // 設定 device.system.uptime, 會是 MCM_DSCHANGE_SET.
    path1 = "device.system";
    if(mcm_config_get_entry_self_status_by_path(this_session, path1, &tmp_status)
                                                < MCM_RCODE_PASS)
    {
        DMSG("call mcm_config_get_entry_self_status_by_path(%s) fail", path1);
        goto FREE_01;
    }
    tmp_status &= MCM_DSCHANGE_MASK;
    show_status("entry-self", path1, "", tmp_status);

    // 範例-02a : 取得 device.vap.@2 的狀態.
    // 設定 device.vap.@2, 會是 MCM_DSCHANGE_SET.
    path1 = "device.vap.@2";
    if(mcm_config_get_entry_self_status_by_path(this_session, path1, &tmp_status)
                                                < MCM_RCODE_PASS)
    {
        DMSG("call mcm_config_get_entry_self_status_by_path(%s) fail", path1);
        goto FREE_01;
    }
    tmp_status &= MCM_DSCHANGE_MASK;
    show_status("entry-self", path1, "", tmp_status);

    // 範例-02a-01 : 取得 device.vap.@2.extra 的狀態.
    // 設定不會影響到 child-group, 所以會是 MCM_DSCHANGE_NONE.
    path1 = "device.vap.@2.extra";
    if(mcm_config_get_entry_self_status_by_path(this_session, path1, &tmp_status)
                                                < MCM_RCODE_PASS)
    {
        DMSG("call mcm_config_get_entry_self_status_by_path(%s) fail", path1);
        goto FREE_01;
    }
    tmp_status &= MCM_DSCHANGE_MASK;
    show_status("entry-self", path1, "", tmp_status);

    // 範例-02b : 取得 device.vap.#51 的狀態.
    // 增加 device.vap.#51, 會是 MCM_DSCHANGE_ADD.
    path1 = "device.vap.#51";
    if(mcm_config_get_entry_self_status_by_path(this_session, path1, &tmp_status)
                                                < MCM_RCODE_PASS)
    {
        DMSG("call mcm_config_get_entry_self_status_by_path(%s) fail", path1);
        goto FREE_01;
    }
    tmp_status &= MCM_DSCHANGE_MASK;
    show_status("entry-self", path1, "", tmp_status);

    // 範例-02b-01 : 取得 device.vap.#51.extra 的狀態.
    // 增加會一起增加 gs 類型的 child-group, 所以會是 MCM_DSCHANGE_ADD.
    path1 = "device.vap.#51.extra";
    if(mcm_config_get_entry_self_status_by_path(this_session, path1, &tmp_status)
                                                < MCM_RCODE_PASS)
    {
        DMSG("call mcm_config_get_entry_self_status_by_path(%s) fail", path1);
        goto FREE_01;
    }
    tmp_status &= MCM_DSCHANGE_MASK;
    show_status("entry-self", path1, "", tmp_status);

    // 範例-02c : 取得 device.vap.#8 的狀態.
    // 刪除 device.vap.#8, 會是 MCM_DSCHANGE_DEL.
    path1 = "device.vap.#8";
    if(mcm_config_get_entry_self_status_by_path(this_session, path1, &tmp_status)
                                                < MCM_RCODE_PASS)
    {
        DMSG("call mcm_config_get_entry_self_status_by_path(%s) fail", path1);
        goto FREE_01;
    }
    tmp_status &= MCM_DSCHANGE_MASK;
    show_status("entry-self", path1, "", tmp_status);

    // 範例-02c-01 : 取得 device.vap.#8.extra 的狀態.
    // 刪除會一起刪除 child-group, 所以會是 MCM_DSCHANGE_DEL.
    path1 = "device.vap.#8.extra";
    if(mcm_config_get_entry_self_status_by_path(this_session, path1, &tmp_status)
                                                < MCM_RCODE_PASS)
    {
        DMSG("call mcm_config_get_entry_self_status_by_path(%s) fail", path1);
        goto FREE_01;
    }
    tmp_status &= MCM_DSCHANGE_MASK;
    show_status("entry-self", path1, "", tmp_status);

    // 範例-02c-02 : 取得 device.vap.#8.station.@1 的狀態.
    // 刪除會一起刪除 child-group, 所以會是 MCM_DSCHANGE_DEL.
    path1 = "device.vap.#8.station.@1";
    if(mcm_config_get_entry_self_status_by_path(this_session, path1, &tmp_status)
                                                < MCM_RCODE_PASS)
    {
        DMSG("call mcm_config_get_entry_self_status_by_path(%s) fail", path1);
        goto FREE_01;
    }
    tmp_status &= MCM_DSCHANGE_MASK;
    show_status("entry-self", path1, "", tmp_status);

    // 範例-02d : 取得 device.vap.#23 的狀態.
    // 沒有修改 device.vap.#23, 會是 MCM_DSCHANGE_NONE.
    path1 = "device.vap.#23";
    if(mcm_config_get_entry_self_status_by_path(this_session, path1, &tmp_status)
                                                < MCM_RCODE_PASS)
    {
        DMSG("call mcm_config_get_entry_self_status_by_path(%s) fail", path1);
        goto FREE_01;
    }
    tmp_status &= MCM_DSCHANGE_MASK;
    show_status("entry-self", path1, "", tmp_status);

    fret = MCM_RCODE_PASS;
FREE_01:
    return fret;
}
</pre>
        </td>
      </tr>
    </table>
    <br>

    <div class="css_div_hook" id="hook_0402_mcm_config_get_entry_all_status_by_path_01"></div>
    <table class="css_table_box">
      <tr>
        <td class="css_td_box">
          <font class="css_font_b2">mcm_config_get_entry_all_status_by_path</font><br>
          讀出 entry 中所有 member 的狀態.<br>
          <table class="css_table_list2">
            <tr>
              <td class="css_td_list2_t1">參數</td>
              <td class="css_td_list2_t1">說明</td>
            </tr>
            <tr>
              <td class="css_td_list2_l1">
                <font class="css_font_r1">struct mcm_service_session_t *</font><br>
                <font class="css_font_g1">this_session</font>
              </td>
              <td class="css_td_list2_r1">
                請求端的連線資訊
              </td>
            </tr>
            <tr>
              <td class="css_td_list2_l1">
                <font class="css_font_r1">char *</font><br>
                <font class="css_font_g1">full_path</font><br>
              </td>
              <td class="css_td_list2_r1">
                目標的路徑 <a href="#hook_0402_full_path_01">[詳細]</a><br>
                <font class="css_font_p1">[entry 格式][index / key 模式]</font>
              </td>
            </tr>
            <tr>
              <td class="css_td_list2_l1">
                <font class="css_font_r1">void *</font><br>
                <font class="css_font_g1">data_buf</font><br>
              </td>
              <td class="css_td_list2_r1">
                紀錄資料的狀態的緩衝 (狀態的資料型態 <a href="#hook_0402_typedef_02">[詳細]</a>)
              </td>
            </tr>
          </table>
          <table class="css_table_list2">
            <tr>
              <td class="css_td_list2_t1">回傳</td>
              <td class="css_td_list2_t1">說明</td>
            </tr>
            <tr>
              <td class="css_td_list2_l2">&gt;= MCM_RCODE_PASS</td>
              <td class="css_td_list2_r1">成功</td>
            </tr>
            <tr>
              <td class="css_td_list2_l2">&nbsp;&lt; MCM_RCODE_PASS<br>(MCM_RCODE_CONFIG_NOT_FIND_STORE)</td>
              <td class="css_td_list2_r1">錯誤, 目標 entry 不存在</td>
            </tr>
            <tr>
              <td class="css_td_list2_l2">&nbsp;&lt; MCM_RCODE_PASS<br>(other)</td>
              <td class="css_td_list2_r1">錯誤, 其他錯誤</td>
            </tr>
          </table>
          <br>
          範例 :<br>
<pre class="css_pre_code">
外部程式部分

#include &lt;errno.h&gt;
#include &lt;stdio.h&gt;
#include &lt;string.h&gt;
#include &lt;stdlib.h&gt;
#include "mcm_lib/mcm_lheader/mcm_type.h"
#include "mcm_lib/mcm_lheader/mcm_size.h"
#include "mcm_lib/mcm_lheader/mcm_connect.h"
#include "mcm_lib/mcm_lheader/mcm_return.h"
#include "mcm_lib/mcm_lheader/mcm_data_exinfo_auto.h"
#include "mcm_lib/mcm_lulib/mcm_lulib_api.h"

#define DMSG(msg_fmt, msgs...) printf("%s(%04u): " msg_fmt "\n", __FILE__, __LINE__, ##msgs)

int main(
    int argc,
    char **argv)
{
    char *path1;
    struct mcm_lulib_lib_t self_lulib;
    MCM_DTYPE_ISLL_TD uptime;
    struct mcm_dv_device_vap_t vap_v;

    self_lulib.socket_path = "@mintcm";
    self_lulib.call_from = MCM_CFROM_USER;
    self_lulib.session_permission = MCM_SPERMISSION_RW;
    self_lulib.session_stack_size = 0;
    if(mcm_lulib_init(&self_lulib) < MCM_RCODE_PASS)
    {
        DMSG("call mcm_lulib_init() fail");
        goto FREE_01;
    }

    // 範例-01 : 設定 device.system.uptime
    path1 = "device.system.uptime";
    uptime = 123456;
    DMSG("[set] %s", path1);
    if(mcm_lulib_set_alone(&self_lulib, path1, &uptime, sizeof(uptime)) < MCM_RCODE_PASS)
    {
        DMSG("call mcm_lulib_set_alone(%s) fail", path1);
        goto FREE_02;
    }

    // 範例-02a : 設定 device.vap.@2
    path1 = "device.vap.@2";
    memset(&vap_v, 0, sizeof(struct mcm_dv_device_vap_t));
    snprintf(vap_v.ssid, sizeof(vap_v.ssid), "ap-1234");
    vap_v.channel = 14;
    DMSG("[set] %s", path1);
    if(mcm_lulib_set_entry(&self_lulib, path1, &vap_v, sizeof(vap_v)) < MCM_RCODE_PASS)
    {
        DMSG("call mcm_lulib_set_entry(%s) fail", path1);
        goto FREE_02;
    }

    // 範例 02b : 增加 device.vap.#51
    path1 = "device.vap.#51";
    DMSG("[add] %s", path1);
    if(mcm_lulib_add_entry(&self_lulib, path1, NULL, NULL, 0) < MCM_RCODE_PASS)
    {
        DMSG("call mcm_lulib_add_entry(%s) fail", path1);
        goto FREE_02;
    }

    // 範例 02c : 刪除 device.vap.#8
    path1 = "device.vap.#8";
    DMSG("[del] %s", path1);
    if(mcm_lulib_del_entry(&self_lulib, path1) < MCM_RCODE_PASS)
    {
        DMSG("call mcm_lulib_del_entry(%s) fail", path1);
        goto FREE_02;
    }

    // 呼叫內部模組處理.
    path1 = "mcm_module_status_test_get_entry_all";
    DMSG("[run] %s", path1);
    if(mcm_lulib_run(&self_lulib, path1, NULL, 0, NULL, NULL) < MCM_RCODE_PASS)
    {
        DMSG("call mcm_lulib_run(%s) fail", path1);
        goto FREE_02;
    }

FREE_02:
    mcm_lulib_exit(&self_lulib);
FREE_01:
    return 0;
}
</pre>
<br>
<pre class="css_pre_code">
內部模組部分

#include &lt;stdio.h&gt;
#include "mcm_lib/mcm_lheader/mcm_type.h"
#include "mcm_lib/mcm_lheader/mcm_size.h"
#include "mcm_lib/mcm_lheader/mcm_control.h"
#include "mcm_lib/mcm_lheader/mcm_connect.h"
#include "mcm_lib/mcm_lheader/mcm_return.h"
#include "mcm_lib/mcm_lheader/mcm_debug.h"
#include "mcm_lib/mcm_lheader/mcm_data_exinfo_auto.h"
#include "../mcm_service_handle_define.h"
#include "../mcm_config_handle_extern.h"

#define DMSG(msg_fmt, msgs...) printf("%s(%04u): " msg_fmt "\n", __FILE__, __LINE__, ##msgs)

void show_status(
    char *case_name,
    char *path_name,
    char *post_name,
    MCM_DTYPE_DS_TD status_code)
{
    char *status_type = NULL;

    switch(status_code)
    {
        case MCM_DSCHANGE_NONE:
            status_type = "non";
            break;
        case MCM_DSCHANGE_SET:
            status_type = "set";
            break;
        case MCM_DSCHANGE_ADD:
            status_type = "add";
            break;
        case MCM_DSCHANGE_DEL:
            status_type = "del";
            break;
    }

    DMSG("[%s] %s %s%s", case_name, status_type, path_name, post_name);
}

int mcm_module_status_test_get_entry_all(
    struct mcm_service_session_t *this_session)
{
    int fret = MCM_RCODE_MODULE_INTERNAL_ERROR;
    char *path1;
    struct mcm_ds_device_t device_s;
    struct mcm_ds_device_system_t system_s;
    struct mcm_ds_device_vap_t vap_s;
    struct mcm_ds_device_vap_extra_t extra_s;
    struct mcm_ds_device_vap_station_t station_s;

    // 範例 : 取得 device 的狀態.
    // 沒有修改 device, 會是 MCM_DSCHANGE_NONE.
    path1 = "device";
    if(mcm_config_get_entry_all_status_by_path(this_session, path1, &device_s) < MCM_RCODE_PASS)
    {
        DMSG("call mcm_config_get_entry_all_status_by_path(%s) fail", path1);
        goto FREE_01;
    }
    device_s.ekey &= MCM_DSCHANGE_MASK;
    device_s.descript &= MCM_DSCHANGE_MASK;
    device_s.serial_number &= MCM_DSCHANGE_MASK;
    show_status("entry-all", path1, "", device_s.ekey);
    show_status("entry-all", path1, ".descript", device_s.descript);
    show_status("entry-all", path1, ".serial_number", device_s.serial_number);

    // 範例-01 : 取得 device.system 的狀態.
    // 設定 device.system.uptime, 會是 MCM_DSCHANGE_SET.
    path1 = "device.system";
    if(mcm_config_get_entry_all_status_by_path(this_session, path1, &system_s) < MCM_RCODE_PASS)
    {
        DMSG("call mcm_config_get_entry_all_status_by_path(%s) fail", path1);
        goto FREE_01;
    }
    system_s.ekey &= MCM_DSCHANGE_MASK;
    system_s.date &= MCM_DSCHANGE_MASK;
    system_s.ip_addr &= MCM_DSCHANGE_MASK;
    system_s.uptime &= MCM_DSCHANGE_MASK;
    system_s.loading &= MCM_DSCHANGE_MASK;
    show_status("entry-all", path1, "", system_s.ekey);
    show_status("entry-all", path1, ".date", system_s.date);
    show_status("entry-all", path1, ".ip_addr", system_s.ip_addr);
    show_status("entry-all", path1, ".uptime", system_s.uptime);
    show_status("entry-all", path1, ".loading", system_s.loading);

    // 範例-02a : 取得 device.vap.@2 的狀態.
    // 設定 device.vap.@2, 會是 MCM_DSCHANGE_SET.
    path1 = "device.vap.@2";
    if(mcm_config_get_entry_all_status_by_path(this_session, path1, &vap_s) < MCM_RCODE_PASS)
    {
        DMSG("call mcm_config_get_entry_all_status_by_path(%s) fail", path1);
        goto FREE_01;
    }
    vap_s.ekey &= MCM_DSCHANGE_MASK;
    vap_s.ssid &= MCM_DSCHANGE_MASK;
    vap_s.channel &= MCM_DSCHANGE_MASK;
    show_status("entry-all", path1, "", vap_s.ekey);
    show_status("entry-all", path1, ".ssid", vap_s.ssid);
    show_status("entry-all", path1, ".channel", vap_s.channel);

    // 範例-02a-01 : 取得 device.vap.@2.extra 的狀態.
    // 設定不會影響到 child-group, 所以會是 MCM_DSCHANGE_NONE.
    path1 = "device.vap.@2.extra";
    if(mcm_config_get_entry_all_status_by_path(this_session, path1, &extra_s) < MCM_RCODE_PASS)
    {
        DMSG("call mcm_config_get_entry_all_status_by_path(%s) fail", path1);
        goto FREE_01;
    }
    extra_s.ekey &= MCM_DSCHANGE_MASK;
    extra_s.hidden &= MCM_DSCHANGE_MASK;
    extra_s.tx_power &= MCM_DSCHANGE_MASK;
    show_status("entry-all", path1, "", extra_s.ekey);
    show_status("entry-all", path1, ".hidden", extra_s.hidden);
    show_status("entry-all", path1, ".tx_power", extra_s.tx_power);

    // 範例-02b : 取得 device.vap.#51 的狀態.
    // 增加 device.vap.#51, 會是 MCM_DSCHANGE_ADD.
    path1 = "device.vap.#51";
    if(mcm_config_get_entry_all_status_by_path(this_session, path1, &vap_s) < MCM_RCODE_PASS)
    {
        DMSG("call mcm_config_get_entry_all_status_by_path(%s) fail", path1);
        goto FREE_01;
    }
    vap_s.ekey &= MCM_DSCHANGE_MASK;
    vap_s.ssid &= MCM_DSCHANGE_MASK;
    vap_s.channel &= MCM_DSCHANGE_MASK;
    show_status("entry-all", path1, "", vap_s.ekey);
    show_status("entry-all", path1, ".ssid", vap_s.ssid);
    show_status("entry-all", path1, ".channel", vap_s.channel);

    // 範例-02b-01 : 取得 device.vap.#51.extra 的狀態.
    // 增加會一起增加 gs 類型的 child-group, 所以會是 MCM_DSCHANGE_ADD.
    path1 = "device.vap.#51.extra";
    if(mcm_config_get_entry_all_status_by_path(this_session, path1, &extra_s) < MCM_RCODE_PASS)
    {
        DMSG("call mcm_config_get_entry_all_status_by_path(%s) fail", path1);
        goto FREE_01;
    }
    extra_s.ekey &= MCM_DSCHANGE_MASK;
    extra_s.hidden &= MCM_DSCHANGE_MASK;
    extra_s.tx_power &= MCM_DSCHANGE_MASK;
    show_status("entry-all", path1, "", extra_s.ekey);
    show_status("entry-all", path1, ".hidden", extra_s.hidden);
    show_status("entry-all", path1, ".tx_power", extra_s.tx_power);

    // 範例-02c : 取得 device.vap.#8 的狀態.
    // 刪除 device.vap.#8, 會是 MCM_DSCHANGE_DEL.
    path1 = "device.vap.#8";
    if(mcm_config_get_entry_all_status_by_path(this_session, path1, &vap_s) < MCM_RCODE_PASS)
    {
        DMSG("call mcm_config_get_entry_all_status_by_path(%s) fail", path1);
        goto FREE_01;
    }
    vap_s.ekey &= MCM_DSCHANGE_MASK;
    vap_s.ssid &= MCM_DSCHANGE_MASK;
    vap_s.channel &= MCM_DSCHANGE_MASK;
    show_status("entry-all", path1, "", vap_s.ekey);
    show_status("entry-all", path1, ".ssid", vap_s.ssid);
    show_status("entry-all", path1, ".channel", vap_s.channel);

    // 範例-02c-01 : 取得 device.vap.#8.extra 的狀態.
    // 刪除會一起刪除 child-group, 所以會是 MCM_DSCHANGE_DEL.
    path1 = "device.vap.#8.extra";
    if(mcm_config_get_entry_all_status_by_path(this_session, path1, &extra_s) < MCM_RCODE_PASS)
    {
        DMSG("call mcm_config_get_entry_all_status_by_path(%s) fail", path1);
        goto FREE_01;
    }
    extra_s.ekey &= MCM_DSCHANGE_MASK;
    extra_s.hidden &= MCM_DSCHANGE_MASK;
    extra_s.tx_power &= MCM_DSCHANGE_MASK;
    show_status("entry-all", path1, "", extra_s.ekey);
    show_status("entry-all", path1, ".hidden", extra_s.hidden);
    show_status("entry-all", path1, ".tx_power", extra_s.tx_power);

    // 範例-02c-02 : 取得 device.vap.#8.station.@1 的狀態.
    // 刪除會一起刪除 child-group, 所以會是 MCM_DSCHANGE_DEL.
    path1 = "device.vap.#8.station.@1";
    if(mcm_config_get_entry_all_status_by_path(this_session, path1, &station_s) < MCM_RCODE_PASS)
    {
        DMSG("call mcm_config_get_entry_all_status_by_path(%s) fail", path1);
        goto FREE_01;
    }
    station_s.ekey &= MCM_DSCHANGE_MASK;
    station_s.mac_addr &= MCM_DSCHANGE_MASK;
    station_s.rule &= MCM_DSCHANGE_MASK;
    show_status("entry-all", path1, "", station_s.ekey);
    show_status("entry-all", path1, ".mac_addr", station_s.mac_addr);
    show_status("entry-all", path1, ".rule", station_s.rule);

    // 範例-02d : 取得 device.vap.#23 的狀態.
    // 沒有修改 device.vap.#23, 會是 MCM_DSCHANGE_NONE.
    path1 = "device.vap.#23";
    if(mcm_config_get_entry_all_status_by_path(this_session, path1, &vap_s) < MCM_RCODE_PASS)
    {
        DMSG("call mcm_config_get_entry_all_status_by_path(%s) fail", path1);
        goto FREE_01;
    }
    vap_s.ekey &= MCM_DSCHANGE_MASK;
    vap_s.ssid &= MCM_DSCHANGE_MASK;
    vap_s.channel &= MCM_DSCHANGE_MASK;
    show_status("entry-all", path1, "", vap_s.ekey);
    show_status("entry-all", path1, ".ssid", vap_s.ssid);
    show_status("entry-all", path1, ".channel", vap_s.channel);

    fret = MCM_RCODE_PASS;
FREE_01:
    return fret;
}
</pre>
        </td>
      </tr>
    </table>
    <br>

  </div>
</div>
<br>

<div class="css_div_box_frame_full">
  <div class="css_div_box_title">範例程式的使用</div>
  <div class="css_div_box_content">
    <br>

    <table class="css_table_list1">
      <tr>
        <td class="css_td_list1_l">01.&nbsp;</td>
        <td class="css_td_list1_r">
          範例程式目錄在 <font class="css_font_b1">mint_cm/usage/example/0402</font>.
        </td>
      </tr>
    </table>
    <br><br>

    <table class="css_table_list1">
      <tr>
        <td class="css_td_list1_l">02.&nbsp;</td>
        <td class="css_td_list1_r">
          下面關於 <font class="css_font_p1">make</font> 的操作沒有特別註明的話都是在
          <font class="css_font_b1">mint_cm</font> 目錄.
        </td>
      </tr>
    </table>
    <br><br>

    <table class="css_table_list1">
      <tr>
        <td class="css_td_list1_l">03.&nbsp;</td>
        <td class="css_td_list1_r">
          第一次使用, 使用 <font class="css_font_p1">make example_add KEY=0402</font>
          載入範例並編譯.
        </td>
      </tr>
    </table>
    <br><br>

    <table class="css_table_list1">
      <tr>
        <td class="css_td_list1_l">04.&nbsp;</td>
        <td class="css_td_list1_r">
          <font class="css_font_b1">web_app</font> 是範例程式.<br><br>
          範例項目 :<br>
          <table class="css_table_list2">
            <tr>
              <td class="css_td_list2_l2">case-01</td>
              <td class="css_td_list2_r1">對 device 做設定資料測試</td>
            </tr>
            <tr>
              <td class="css_td_list2_l2">case-02</td>
              <td class="css_td_list2_r1">對 device.system 做設定資料測試</td>
            </tr>
            <tr>
              <td class="css_td_list2_l2">case-03a</td>
              <td class="css_td_list2_r1">對 device.vap.* 做設定資料測試</td>
            </tr>
            <tr>
              <td class="css_td_list2_l2">case-03b</td>
              <td class="css_td_list2_r1">對 device.vap.* 做增加資料測試</td>
            </tr>
            <tr>
              <td class="css_td_list2_l2">case-03c</td>
              <td class="css_td_list2_r1">對 device.vap.* 做刪除資料測試</td>
            </tr>
            <tr>
              <td class="css_td_list2_l2">case-04a</td>
              <td class="css_td_list2_r1">對 device.vap.*.station.* 做設定資料測試</td>
            </tr>
            <tr>
              <td class="css_td_list2_l2">case-04b</td>
              <td class="css_td_list2_r1">對 device.vap.*.station.* 做增加資料測試</td>
            </tr>
            <tr>
              <td class="css_td_list2_l2">case-04c</td>
              <td class="css_td_list2_r1">對 device.vap.*.station.* 做刪除資料測試</td>
            </tr>
          </table>
        </td>
      </tr>
    </table>
    <br><br>

    <table class="css_table_list1">
      <tr>
        <td class="css_td_list1_l">05.&nbsp;</td>
        <td class="css_td_list1_r">
          先執行 mcm_daemon 和 mini_httpd 才可測試.
        </td>
      </tr>
    </table>
    <br><br>

    <table class="css_table_list1">
      <tr>
        <td class="css_td_list1_l">06.&nbsp;</td>
        <td class="css_td_list1_r">
          瀏覽器連至 <font class="css_font_b1">http://&lt;server-address&gt;/web_app_0402_index.html</font>
          就可以看到範例頁面.
        </td>
      </tr>
    </table>
    <br><br>

    <table class="css_table_list1">
      <tr>
        <td class="css_td_list1_l">07.&nbsp;</td>
        <td class="css_td_list1_r">
          測試完畢不使用後, 使用 <font class="css_font_p1">make example_del KEY=0402</font>
          將範例移除.
        </td>
      </tr>
    </table>
    <br><br>

    <table class="css_table_list1">
      <tr>
        <td class="css_td_list1_l">08.&nbsp;</td>
        <td class="css_td_list1_r">
          範例程式目錄下的檔案在做完 <font class="css_font_p1">make example_add</font>
          後會複製到真正使用的位置, 要修改做測試的話要改在複製後的.<br>
          <table class="css_table_list2">
            <tr>
              <td class="css_td_list2_r1">
                來源 <font class="css_font_b1">profile/mcm_data_profile_0402.xml</font><br>
                目地 <font class="css_font_b1">mint_cm/mcm_build/mcm_data_profile.xml</font><br>
                資料模型範例<br>
                有修改要使用 <font class="css_font_p1">make all</font> 重新編譯
              </td>
            </tr>
            <tr>
              <td class="css_td_list2_r1">
                來源 <font class="css_font_b1">profile/mcm_store_profile_default_0402.txt</font><br>
                目地 <font class="css_font_b1">mint_cm/mcm_build/mcm_store_profile_default.txt</font><br>
                資料預設值範例<br>
                使用 <font class="css_font_p1">make all</font> 後會再複製到 <font class="css_font_b1">mint_cm/run</font>
              </td>
            </tr>
            <tr>
              <td class="css_td_list2_r1">
                來源 <font class="css_font_b1">web_app</font><br>
                目地 <font class="css_font_b1">mint_cm/run/web</font><br>
                網頁程式範例
              </td>
            </tr>
            <tr>
              <td class="css_td_list2_r1">
                來源 <font class="css_font_b1">module/mcm_module_0402.c</font><br>
                目地 <font class="css_font_b1">mint_cm/mcm_daemon/mcm_module</font><br>
                內部模組範例<br>
                有修改要使用 <font class="css_font_p1">make all</font> 重新編譯
              </td>
            </tr>
          </table>
        </td>
      </tr>
    </table>
    <br>

  </div>
</div>
<br>

</body>

</html>
